package k8s

import (
	"context"
	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
)

type ConfigMap interface {
	CreateConfigMap(namespace string, cm *corev1.ConfigMap) error
	CreateIfNotExistsConfigMap(namespace string, cm *corev1.ConfigMap) error
}

// ConfigMapService is the configMap service implementation using API calls to kubernetes.
type ConfigMapService struct {
	kubeClient kubernetes.Interface
	logger     logr.Logger
}

// newConfigMapService returns a new ConfigMap KubeService.
func newConfigMapService(kubeClient kubernetes.Interface, logger logr.Logger) *ConfigMapService {
	logger = logger.WithValues("service", "k8s.configMap")
	return &ConfigMapService{
		kubeClient: kubeClient,
		logger:     logger,
	}
}

func (p *ConfigMapService) CreateConfigMap(namespace string, cm *corev1.ConfigMap) error {
	_, err := p.kubeClient.CoreV1().ConfigMaps(namespace).Create(context.TODO(), cm, metav1.CreateOptions{})
	if err != nil {
		return err
	}
	p.logger.WithValues("namespace", namespace).WithValues("configMap", cm.Name).Info("configMap created")
	return nil
}

func (p *ConfigMapService) CreateIfNotExistsConfigMap(namespace string, cm *corev1.ConfigMap) error {
	_, err := p.kubeClient.CoreV1().ConfigMaps(namespace).Update(context.TODO(), cm, metav1.UpdateOptions{})
	if err != nil {
		// if resource not exist
		if errors.IsNotFound(err) {
			return p.CreateConfigMap(namespace, cm)
		}
		return err
	}
	return nil
}
